python 多线程、线程池及队列的基础使用(Thread ThreadPoolExecutor Queue)

您所在的位置:网站首页 python 多线程处理任务 python 多线程、线程池及队列的基础使用(Thread ThreadPoolExecutor Queue)

python 多线程、线程池及队列的基础使用(Thread ThreadPoolExecutor Queue)

2024-06-26 14:57:31| 来源: 网络整理| 查看: 265

本文链接:https://www.cnblogs.com/tujia/p/13565799.html

 

背景:单线程处理任务是阻塞式,一个一个任务处理的,在处理大量任务的时候,消耗时间长;同时如果服务器配置还不错的话,光跑一个单线程的话,也有点浪费了配置了

多线程:多线程是异步、并发的,可以大大提高程序的IO处理速度,更好的利用系统资源,更快完成任务

 

Talk is cheap. Show me the code。下面就直接上代码了~

 

一、简单多线程

# 简单多线程 # 解释: # 1)一个工人只做一个任务,做完就撤了; # 2)有多少个任务就得有多少个工人; # 3)这个方式处理任务需要快,但人员成本开销高。 # @see https://docs.python.org/zh-cn/3/library/threading.html?highlight=threading#threading.Thread import threading # 任务 def task(taskId): thread_name = threading.current_thread().getName() print('工人【%s】正在处理任务【%d】:do something...' % (thread_name, taskId)) def main(): threads = [] # 这里弄5个线程(一个线程相当于一个工人) for i in range(5): # target 参数指定线程要处理的任务函数,args 参数传递参数到任务函数去 t = threading.Thread(target=task, args=(i+1,)) # 启动线程 t.start() threads.append(t) # 阻塞线程 for t in threads: t.join() if __name__ == '__main__': main()

执行结果:

 

二、线程池

正如上面注释里说的,线程虽好,但太多线程的话,资源(cpu、内存等)的消耗也挺大的;而且线程都是处理完一个任务就“死”掉了,不能复用,有点浪费

于是,这个“线程池”这个东西出现了。线程池就是管理线程的池子,池子如果设置容量,控制好线程的数量,也就控制好了资源的消耗~

# 线程池 # 解释: # 1)一个工人同一时间只做一个任务,但做完一个任务可以接着做下一个任务; # 2)可以分配多个任务给少量工人,减少人员成本开销。 # @see https://docs.python.org/zh-cn/3/library/concurrent.futures.html import threading from concurrent.futures import ThreadPoolExecutor # 任务 def task(taskId): thread_name = threading.current_thread().getName() print('工人【%s】正在处理任务【%d】:do something...' % (thread_name, taskId)) def main(): # 初始化线程池(商会),定义好池里最多有几个工人 pool = ThreadPoolExecutor(max_workers=5, thread_name_prefix='Thread') # 准备10个任务 for i in range(10): # 提交任务到池子(商会)里(它会自动分配给工人) pool.submit(task, i+1) if __name__ == '__main__': main()

注:这里把线程池比喻成了“商会”,线程比喻成“工人”,方便大家理解。

执行结果:

 注:从上图可以看到线程被复用了,而且 Thread_0 被复用了最多次,而 Thread_4 毫无用武之地,没有使用到(你可以把任务数量调大,看看结果又会是怎么样?)

 

三、线程池2

这里的示例和上面是一样的,只是加了一点代码来模拟任务耗时,方便大家观察线程池是怎么分配任务的

# 线程池 # 解释: # 1)一个工人同一时间只做一个任务,但做完一个任务可以接着做下一个任务; # 2)可以分配多个任务给少量工人,减少人员成本开销。 # 3)任务按顺序分配给空闲工人,但每个任务的耗时不一样,任务不是按顺序被完成的,后提交的任务可能会先被完成 import time import random import threading from concurrent.futures import ThreadPoolExecutor # 任务 def task(taskId, consuming): thread_name = threading.current_thread().getName() print('工人【%s】正在处理任务【%d】:do something...' % (thread_name, taskId)) # 模拟任务耗时(秒) time.sleep(consuming) print('任务【%d】:done' % taskId) def main(): # 5个工人 pool = ThreadPoolExecutor(max_workers=5, thread_name_prefix='Thread') # 准备10个任务 for i in range(10): # 模拟任务耗时(秒) consuming = random.randint(1, 5) pool.submit(task, i+1, consuming) if __name__ == '__main__': main()

执行结果:

 注:看执行结果来看,不难发现:多线程是异步的,且会并发

 

三、队列

除了使用线程池,我们还可以使用队列来处理任务。任务排好队,工人(线程)按顺序不断从队列里取任务,处理任务~

# 线程队列 # 解释: # 1)一个队列有N个工人在排队,按队列排序给他们分配任务; # 2)做得再快,也要按排队排序来接任务,不能插队抢任务。 # @see https://docs.python.org/zh-cn/3/library/queue.html#queue-objects import time import random import threading from queue import Queue # 自定义线程 class CustomThread(threading.Thread): def __init__(self, queue, **kwargs): super(CustomThread, self).__init__(**kwargs) self.__queue = queue def run(self): while True: # (工人)获取任务 item = self.__queue.get() # 执行任务 item[0](*item[1:]) # 告诉队列,任务已完成 self.__queue.task_done() # 任务 def task(taskId, consuming): thread_name = threading.current_thread().getName() print('工人【%s】正在处理任务【%d】:do something...' % (thread_name, taskId)) # 模拟任务耗时(秒) time.sleep(consuming) print('任务【%d】:done' % taskId) def main(): q = Queue() # 招工,这里招了5个工人(启动5个线程) for i in range(5): t = CustomThread(q, daemon=True) # 工人已经准备好接活了 t.start() # 来活了(往队列里塞任务) for i in range(10): taskId = i + 1 # 模拟任务耗时(秒) consuming = random.randint(1, 5) q.put((task, taskId, consuming)) # 阻塞队列 q.join() if __name__ == '__main__': main()

执行结果:

注1:这里用了一个自定义线程类,具体可以看这里:https://docs.python.org/zh-cn/3/library/queue.html#queue-objects

注2:简单来说,就是先招固定的N个工人(创建N个线程),让它们盯着任务队列;然后往队列里塞任务;事先盯着队列的工人们发现有任务,就开始接任务、处理任务了

注3:while True 的意思是循环(不断)地从任务队列里取任务,如果不用 while True的话,线程处理完一个任务就会结束,无法复用,任务也无法全部处理完

注4:这里的线程不能使用 Tread.join 方法,join(阻塞线程)方法会和 while True 冲突,使线程无法结束,一直阻塞着

注5:while True 最后是如何自动结束掉的,目前我还不太了解。希望知道原理的大大能告诉我一下~

 

本文链接:https://www.cnblogs.com/tujia/p/13565799.html

完。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭